home *** CD-ROM | disk | FTP | other *** search
/ ADA Programming Guide / ADA Programming Guide.iso / ada_gwu / predef2.c < prev    next >
C/C++ Source or Header  |  1996-01-30  |  15KB  |  463 lines

  1. /*
  2.  * Copyright (C) 1985-1992  New York University
  3.  * 
  4.  * This file is part of the Ada/Ed-C system.  See the Ada/Ed README file for
  5.  * warranty (none) and distribution info and also the GNU General Public
  6.  * License for more details.
  7.  
  8.  */
  9. /*    +---------------------------------------------------+
  10.       |                                                   |
  11.       |          I N T E R P     P R E D E F S            |
  12.       |            Part 2: CALENDAR Procedure             |
  13.       |                  (C Version)                      |
  14.       |                                                   |
  15.       |   Adapted From Low Level SETL version written by  |
  16.       |                                                   |
  17.       |                  Monte Zweben                     |
  18.       |               Philippe Kruchten                   |
  19.       |               Jean-Pierre Rosen                   |
  20.       |                                                   |
  21.       |    Original High Level SETL version written by    |
  22.       |                                                   |
  23.       |                   Clint Goss                      |
  24.       |               Tracey M. Siesser                   |
  25.       |               Bernard D. Banner                   |
  26.       |               Stephen C. Bryant                   |
  27.       |                  Gerry Fisher                     |
  28.       |                                                   |
  29.       |              C version written by                 |
  30.       |                                                   |
  31.       |               Robert B. K. Dewar                  |
  32.       |                                                   |
  33.       +---------------------------------------------------+
  34. */
  35.  
  36. /* This module contains the implementation of the CALENDAR package */
  37.  
  38. #include "ipredef.h"
  39. #include "time.h"
  40. #include "intbp.h"
  41. #include "intcp.h"
  42. #include "predefp.h"
  43. #include <conio.h>
  44.  
  45. /* Structure corresponding to Ada record TIME */
  46.  
  47. struct time_record {
  48.     int     year_val;
  49.     int     month_val;
  50.     int     day_val;
  51.     long    secs_val;
  52. };
  53.  
  54. static long days_in(int, int, int);
  55. static void ymd_of(long days, int *, int *, int *);
  56. static void get_time(struct time_record *);
  57.  
  58. /*  Macros for treating pointer as pointer to time_record, and length in
  59.  *  words of time record(used when creating an object of this type.
  60.  */
  61.  
  62. #define TIME_RECORD(ptr)    ((struct time_record *)(ptr))
  63. #define WORDS_TIME_RECORD   (sizeof(struct time_record) / sizeof (int))
  64.  
  65. /*  Constants for CALENDAR */
  66.  
  67. #define ONE_DAY   86400000L       /* 24 * 60 * 60 * 1000 (milliseconds) */
  68.  
  69. static int days_before_month[] = {
  70.     0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
  71. };
  72.  
  73. static int days_in_month[] = {
  74.     0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  75. };
  76.  
  77.  
  78. /* CALENDAR */
  79.  
  80. /* Control passes to the CALENDAR procedure from PREDEF when it encounters an
  81.  * operation code value corresponding to a predefined calendar operation.
  82. */
  83.  
  84. void calendar()                                               /*;calendar*/
  85. {
  86.     switch(operation) {
  87.  
  88.         /* function CLOCK return TIME; */
  89.  
  90.     case P_CLOCK:
  91.         {
  92.             int    bse, off;
  93.             int    *ptr;
  94.  
  95.             create(WORDS_TIME_RECORD, &bse, &off, &ptr);
  96.             get_time((struct time_record  *) ptr);
  97.             TOSM(1) = bse;
  98.             TOS = off;
  99.             break;
  100.         }
  101.  
  102.  
  103.         /* function YEAR(DATE : in TIME) return YEAR_NUMBER; */
  104.  
  105.     case P_YEAR:
  106.         TOSM(2) = TIME_RECORD(get_argument_ptr(0)) -> year_val;
  107.         break;
  108.  
  109.         /* function MONTH(DATE : in TIME) return MONTH_NUMBER; */
  110.  
  111.     case P_MONTH:
  112.         TOSM(2) = TIME_RECORD(get_argument_ptr(0)) -> month_val;
  113.         break;
  114.  
  115.         /* function DAY(DATE : in TIME) return DAY_NUMBER; */
  116.  
  117.     case P_DAY:
  118.         TOSM(2) = TIME_RECORD(get_argument_ptr(0)) -> day_val;
  119.         break;
  120.  
  121.         /* function SECONDS(DATE : in TIME) return DURATION; */
  122.  
  123.     case P_SECONDS:
  124.         {
  125.             int  bse,off;
  126.             long secs,tmp;
  127.  
  128.             /*TOSM(2) = TIME_RECORD(get_argument_ptr(0)) -> secs_val;*/
  129.             /* direct code needed since TOSML macro wrong */
  130.             /* pop arguments, store long and restore args */
  131.             secs = TIME_RECORD(get_argument_ptr(0)) -> secs_val;
  132.  
  133. /*WAS AVL secs = TIME_RECORD(get_argument_ptr(0)) -> secs_val;
  134. */
  135.             POP_ADDR(bse,off);
  136.             POPL(tmp); /* pop current value */
  137.             PUSHL(secs); /* push correct value */
  138.             PUSH_ADDR(bse,off); /* restore arg on stack */
  139.         }
  140.         break;
  141.  
  142.         /* procedure SPLIT(DATE      : in  TIME;          */
  143.         /*                 YEAR      : out YEAR_NUMBER;   */
  144.         /*                 MONTH     : out MONTH_NUMBER;  */
  145.         /*                 DAY       : out DAY_NUMBER;    */
  146.         /*                 SECONDS   : out DURATION);     */
  147.  
  148.     case P_SPLIT:
  149.         {
  150.             struct time_record *time_ptr;
  151.             long *p;
  152.  
  153.             time_ptr = TIME_RECORD(get_argument_ptr(0));
  154.  
  155.             *get_argument_ptr(2)  = time_ptr -> year_val;
  156.             *get_argument_ptr(6)  = time_ptr -> month_val;
  157.             *get_argument_ptr(10) = time_ptr -> day_val;
  158.             p = (long *) get_argument_ptr(14) ;
  159.             *p = time_ptr -> secs_val;
  160.             break;
  161.         }
  162.  
  163.         /* function TIME_OF(YEAR     : YEAR_NUMBER;                   */
  164.         /*                  MONTH    : MONTH_NUMBER;                  */
  165.         /*                  DAY      : DAY_NUMBER;                    */
  166.         /*                  SECONDS  : DURATION := 0.0) return TIME;  */
  167.  
  168.     case P_TIME_OF:
  169.         {
  170.             int    year, month, day;
  171.             long   secs;
  172.             long   days;
  173.             int    bse, off;
  174.             struct time_record *time_ptr;
  175.  
  176.             year  = get_argument_value(0);
  177.             month = get_argument_value(2);
  178.             day   = get_argument_value(4);
  179.             secs  = get_long_argument_value(6);
  180.  
  181.             if ((year % 4) == 0 && month == 2) {
  182.                 if (day > 29) { /* check leap year */
  183.                     raise(TIME_ERROR, "Day too large");
  184.                     return;
  185.                 }
  186.             }
  187.             else if (day > days_in_month[month]) {
  188.                 raise(TIME_ERROR, "Day too large");
  189.                 return;
  190.             }
  191.             if (secs >= ONE_DAY) {
  192.                 secs -= ONE_DAY;
  193.                 days = days_in(year, month, day + 1);
  194.                 ymd_of(days, &year, &month, &day);
  195.                 if (year < 1901 || year > 2099) {
  196.                     raise(TIME_ERROR, "Year out of range");
  197.                     return;
  198.                 }
  199.             }
  200.             create(WORDS_TIME_RECORD, &bse, &off,(int **)(&time_ptr));
  201.             time_ptr -> year_val  = year;
  202.             time_ptr -> month_val = month;
  203.             time_ptr -> day_val   = day;
  204.             time_ptr -> secs_val  = secs;
  205.             TOSM(9) = bse;
  206.             TOSM(8) = off;
  207.             break;
  208.         }
  209.  
  210.         /* function "+"(LEFT : TIME;     RIGHT : DURATION)  return TIME; */
  211.         /* function "+"(LEFT : DURATION; RIGHT : TIME)      return TIME; */
  212.         /* function "-"(LEFT : TIME;     RIGHT : DURATION)  return TIME; */
  213.  
  214.     case P_ADD_TIME_DUR:
  215.     case P_ADD_DUR_TIME:
  216.     case P_SUB_TIME_DUR:
  217.         {
  218.             struct time_record *time_ptr;
  219.             long   dur;
  220.             int    year, month, day;
  221.             long   secs,days;
  222.             int    add_day;
  223.             int    bse, off;
  224.  
  225.             if (operation == P_ADD_TIME_DUR) {
  226.                 time_ptr = TIME_RECORD(get_argument_ptr(0));
  227.                 dur = get_long_argument_value(2);
  228.             }
  229.             else if (operation == P_ADD_DUR_TIME) {
  230.                 dur = get_long_argument_value(0);
  231.                 time_ptr = TIME_RECORD(get_argument_ptr(2));
  232.             }
  233.             else { /* operation == P_SUB_TIME_DUR */
  234.                 time_ptr = TIME_RECORD(get_argument_ptr(0));
  235.                 dur = - get_long_argument_value(2);
  236.             }
  237.  
  238.             year  = time_ptr -> year_val;
  239.             month = time_ptr -> month_val;
  240.             day   = time_ptr -> day_val;
  241.             secs  = time_ptr -> secs_val;
  242.  
  243.             secs += dur;
  244.             add_day = (int)(secs / ONE_DAY);
  245.             secs -= add_day * ONE_DAY;
  246.             if (secs < 0) {
  247.                 secs += ONE_DAY;
  248.                 add_day--;
  249.             }
  250.  
  251.             day += add_day;
  252.  
  253.             days = days_in(year, month, day);
  254.             if (days <= 0) {
  255.                 raise(TIME_ERROR, "Year out of range");
  256.                 return;
  257.             }
  258.             ymd_of(days, &year, &month, &day);
  259.             if (year < 1901 || year > 2099) {
  260.                 raise(TIME_ERROR, "Year out of range");
  261.                 return;
  262.             }
  263.             create(WORDS_TIME_RECORD, &bse, &off,(int **)(&time_ptr));
  264.             time_ptr -> year_val  = year;
  265.             time_ptr -> month_val = month;
  266.             time_ptr -> day_val   = day;
  267.             time_ptr -> secs_val  = secs;
  268.  
  269.             TOSM(5) = bse;
  270.             TOSM(4) = off;
  271.             break;
  272.         }
  273.  
  274.         /* function "-"(LEFT : TIME; RIGHT : TIME) return DURATION; */
  275.  
  276.     case P_SUB_TIME_TIME:
  277.         {
  278.             int    *dur_tt_ptr;
  279.             int    *left_ptr;
  280.             int    *right_ptr;
  281.             int    y1, m1, d1;
  282.             int    y2, m2, d2;
  283.             long   s1, s2, secs, days;
  284.             long   dur;
  285.             struct time_record *time_ptr;
  286.             int    bse, off, bse1, off1;
  287.  
  288.             POP_PTR(dur_tt_ptr);               /* type must be popped */
  289.  
  290.             left_ptr  = get_argument_ptr(0);
  291.             right_ptr = get_argument_ptr(2);
  292.  
  293.             time_ptr = TIME_RECORD(left_ptr);
  294.             y1 = time_ptr -> year_val;
  295.             m1 = time_ptr -> month_val;
  296.             d1 = time_ptr -> day_val;
  297.             s1 = time_ptr -> secs_val;
  298.  
  299.             time_ptr = TIME_RECORD(right_ptr);
  300.             y2 = time_ptr -> year_val;
  301.             m2 = time_ptr -> month_val;
  302.             d2 = time_ptr -> day_val;
  303.             s2 = time_ptr -> secs_val;
  304.  
  305.             days = days_in(y1, m1, d1) - days_in(y2, m2, d2);
  306.             secs = s1 - s2;
  307.             dur = ONE_DAY * days + secs;
  308.  
  309.             if (fix_out_of_bounds(dur, (int *)FX_RANGE(dur_tt_ptr)))
  310.                 raise(TIME_ERROR, "Out of range");
  311.             else {
  312.                 /* direct code needed since TOSML macro wrong */
  313.                 /* pop arguments, store long and restore args */
  314.                 POP_ADDR(bse,off);
  315.                 POP_ADDR(bse1,off1);
  316.                 POPL(secs); /* pop current value */
  317.                 PUSHL(dur); /* push correct value */
  318.                 PUSH_ADDR(bse1,off1); /* restore args on stack */
  319.                 PUSH_ADDR(bse,off);
  320.             }
  321.             break;
  322.         }
  323.  
  324.         /* function "<"  (LEFT, RIGHT : TIME) return BOOLEAN; */
  325.         /* function "<=" (LEFT, RIGHT : TIME) return BOOLEAN; */
  326.         /* function ">"  (LEFT, RIGHT : TIME) return BOOLEAN; */
  327.         /* function ">=" (LEFT, RIGHT : TIME) return BOOLEAN; */
  328.  
  329.     case P_LT_TIME:
  330.     case P_LE_TIME:
  331.     case P_GT_TIME:
  332.     case P_GE_TIME:
  333.         {
  334.             int    *left_ptr;
  335.             int    *right_ptr;
  336.             int    y1, m1, d1;
  337.             int    y2, m2, d2;
  338.             long   s1, s2;
  339.             long   dur1, dur2;
  340.             long   days1, days2;
  341.             struct time_record *time_ptr;
  342.             int    result;
  343.  
  344.             left_ptr  = get_argument_ptr(0);
  345.             right_ptr = get_argument_ptr(2);
  346.  
  347.             time_ptr = TIME_RECORD(left_ptr);
  348.             y1 = time_ptr -> year_val;
  349.             m1 = time_ptr -> month_val;
  350.             d1 = time_ptr -> day_val;
  351.             s1 = time_ptr -> secs_val;
  352.  
  353.             time_ptr = TIME_RECORD(right_ptr);
  354.             y2 = time_ptr -> year_val;
  355.             m2 = time_ptr -> month_val;
  356.             d2 = time_ptr -> day_val;
  357.             s2 = time_ptr -> secs_val;
  358.  
  359.             days1 = days_in(y1, m1, d1);
  360.             days2 = days_in(y2, m2, d2);
  361.             if (days1 == days2) {
  362.                 dur1 = s1;
  363.                 dur2 = s2;
  364.             }
  365.             else {
  366.                 dur1 = days1;
  367.                 dur2 = days2;
  368.             }
  369.  
  370.             if (operation == P_LT_TIME)
  371.                 result = dur1 < dur2;
  372.             else if (operation == P_LE_TIME)
  373.                 result = dur1 <= dur2;
  374.             else if (operation == P_GT_TIME)
  375.                 result = dur1 > dur2;
  376.             else /*(operation == P_GE_TIME) */
  377.                 result = dur1 >= dur2;
  378.  
  379.             TOSM(4) = result;
  380.             break;
  381.         }
  382.     }
  383. }
  384.  
  385.  
  386. /* DAYS_IN */
  387.  
  388. /* Given integer arguments(such as 1981, 2, 28), days_in computes the
  389.  * number of days since January 1st, 1901. Since Ada does not allow dates
  390.  * before 1901 or after 2099, we do not need to consider leap centuries.
  391. */
  392.  
  393. static long days_in(int y, int m, int d)                        /*;days_in*/
  394. {
  395.     return
  396.         (y - 1901) * 365L +(y - 1901) / 4 +
  397.         days_before_month[m] +((y % 4) ? 0 :(m > 2)) + d;
  398. }
  399.  
  400.  
  401. /* YMD_OF */
  402.  
  403. /* Given an integer which is the number of days since January 1st, 1901
  404.  * this function returns the corresponding date in year/month/day form
  405. */
  406.  
  407. static void ymd_of(long days, int *y, int *m, int *d)              /*;ymf_of*/
  408. {
  409.     *y = 1901 +(int)((days * 4 - 1) / 1461);/*(4 * 365 + 1) */
  410.     *d = (int)(days -((*y - 1901) * 365 +(*y - 1901) / 4));
  411.     if (!(*y % 4)) {
  412.         if (*d == 60) {
  413.             *d = 29;
  414.             *m = 2;
  415.             return;
  416.         }
  417.         else if (*d > 60)
  418.             *d -= 1;
  419.     }
  420.     *m = 1;
  421.     while(*d > days_in_month[*m])
  422.         *d -= days_in_month[(*m)++];
  423. }
  424.  
  425. /* GET_TIME */
  426.  
  427. /* Get date and time. The format of the result is:
  428.  *
  429.  *      struct time_record = {
  430.  *         int year_val;
  431.  *         int month_val;
  432.  *         int day_val;
  433.  *         long secs_val;
  434.  *      };
  435. */
  436.  
  437. static void get_time(struct time_record *time_ptr)                /*;get_time*/
  438. {
  439.     long    itime();
  440. int ich;
  441.     /* IBM_PC (Metaware) */
  442.     char time_r[35];
  443.     time_t clock;
  444.     struct tm *t;
  445.     time(&clock);
  446.     t = localtime(&clock);
  447.     time_ptr -> year_val = 1900 + t -> tm_year;
  448.     time_ptr -> month_val = t -> tm_mon + 1;
  449.     time_ptr -> day_val = t -> tm_mday;
  450.     time_ptr -> secs_val =   
  451.           ((long)t->tm_hour*3600 + (long) t->tm_min * 60 
  452.           + (long) t->tm_sec)*1000L;
  453.  
  454.     if (instruction_trace) {
  455.         printf("get_time year %d month %d day %d secs %ld secs_chk %ld\n",
  456.           time_ptr -> year_val, time_ptr -> month_val,
  457.           time_ptr -> day_val, time_ptr -> secs_val, 
  458.           ((long)t->tm_hour*3600 + (long) t->tm_min * 60 
  459.           + (long) t->tm_sec)*1000L);
  460.     }
  461.     return;
  462. }
  463.